' 
' Copyright (C) 2014 Infinity CCS Ltd (http://www.infinityccs.com/)
' Copyright (C) 2008 Sasa Coh <sasacoh@gmail.com>
'
' This program is free software; you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation; either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
' GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program.  If not, see <http://www.gnu.org/licenses/>. 
'/

Imports System
Imports System.Collections.Generic
Imports System.Text

Imports Infinity.pjsipNET.Common
Imports System.Runtime.InteropServices
Imports Infinity.pjsipNET.Common.Config

Public Class pjsipRegistrar
  Inherits IRegistrar

#Region "Dll declarations"
  <DllImport("Infinity.pjsip.dll", EntryPoint:="dll_registerAccount", CallingConvention:=CallingConvention.Cdecl)>
  Private Shared Function dll_registerAccount(uri As String, reguri As String, domain As String, username As String, password As String, proxy As String, isdefault As Boolean) As Integer

  End Function

  <DllImport("Infinity.pjsip.dll", EntryPoint:="dll_removeAccounts", CallingConvention:=CallingConvention.Cdecl)>
  Private Shared Function dll_removeAccounts() As Integer

  End Function
  <DllImportAttribute("Infinity.pjsip.dll", CallingConvention:=CallingConvention.Cdecl)>
  Private Shared Function setCallback_onRegState(cb As delOnRegStateChanged) As Integer

  End Function


#End Region

#Region "Constructor"
  Private Shared _instance As pjsipRegistrar = Nothing
  Public Shared ReadOnly Property Instance As pjsipRegistrar
    Get
      If _instance Is Nothing Then _instance = New pjsipRegistrar()
      Return _instance
    End Get
  End Property

  Private Sub New()
    setCallback_onRegState(rsDel)
  End Sub
#End Region

#Region "Callback declarations"
  '// registration state change delegate
  Delegate Function delOnRegStateChanged(accountId As Integer, regStatus As Integer, regStatusText As String) As Integer

  Shared rsDel As delOnRegStateChanged = New delOnRegStateChanged(AddressOf onRegStateChanged)
#End Region

#Region "Public methods"
  '/////////////////////////////////////////////////////////////////////////////////
  ''' <summary>
  ''' Register all configured accounts 
  ''' </summary>
  ''' <returns></returns>
  Public Overrides Function registerAccounts() As Integer
    If Not pjsipStackProxy.Instance.IsInitialized Then Return -1

    '// unregister accounts
    dll_removeAccounts()

    For Each accountKey As String In Config.AccountKeys
      '// iterate all accounts
      Dim acc As IAccount = Config.Account(accountKey)
      '// check if accounts available
      If acc Is Nothing Then Return -1

      '// reset account Index field
      acc.pjsipIndex = -1
      '// reset account state
      acc.pjsipRegStatus = -1
      acc.pjsipRegStatusText = ""

      If (acc.Enabled AndAlso (acc.UserName.Length > 0) AndAlso (acc.HostName.Length > 0)) Then

        'Dim displayName As String = acc.DisplayName
        '// warning:::Publish do not work if display name in uri !!!
        Dim uri As String = "sip:" + acc.UserName
        If (acc.UserName.IndexOf("@") < 0) Then
          uri += "@" + acc.HostName
        End If
        Dim reguri As String = "sip:" + acc.HostName
        '// check transport - if TCP add transport=TCP
        reguri = pjsipStackProxy.Instance.SetTransport(accountKey, reguri)

        Dim domain As String = acc.DomainName
        Dim username As String = acc.UserName
        Dim password As String = acc.Password

        Dim proxy As String = ""
        If (acc.ProxyAddress.Length > 0) Then
          proxy = "sip:" + acc.ProxyAddress
        End If

        Dim blnDefault As Boolean = (acc.Key = Config.DefaultAccountKey)
        acc.pjsipIndex = dll_registerAccount(uri, reguri, domain, username, password, proxy, blnDefault)
      End If
    Next
    Return 1
  End Function

  ''' <summary>
  ''' Unregister all accounts
  ''' </summary>
  ''' <returns></returns>
  Public Overrides Function unregisterAccounts() As Integer
    Return dll_removeAccounts()
  End Function

  ''' <summary>
  ''' Reception of on registration state change events. First account Id should be mapped to 
  ''' account configuration sequence number.
  ''' </summary>
  ''' <param name="accId"></param>
  ''' <param name="regStatus"></param>
  ''' <returns></returns>
  Private Shared Function onRegStateChanged(accId As Integer, regStatus As Integer, regStatusText As String) As Integer
    '// first map account index
    For Each accountKey As String In Instance.Config.AccountKeys
      Dim account As IAccount = Instance.Config.Account(accountKey)
      If (account.pjsipIndex = accId) Then

        account.pjsipRegStatus = regStatus
        account.pjsipRegStatusText = regStatusText
        Instance.BaseAccountStateChanged(account.AccountName, regStatus, regStatusText)
        Return 1
      End If
    Next
    '// should be here!
    Return -1

  End Function
#End Region
End Class
